#ifndef INIRUN_H
#define INIRUN_H

#include "AliTRDdEdxBaseUtils.h"

void LoadLibs(const Int_t nlib, const TString libs[])
{
  printf("\n");
  for(Int_t ii=0; ii<nlib; ii++){
    printf("Loading %d: %s...\n", ii, libs[ii].Data());
    //Returns 0 on successful loading, 1 in case lib was already loaded, -1 in case lib does not exist or in case of error and -2 in case of version mismatch.
    const Int_t kload = gSystem->Load(Form("lib%s", libs[ii].Data()));
    if(kload!=0){
      printf("load %d: %s fail! %d\n", ii, libs[ii].Data(), kload); exit(1);
    }
  }
  printf("\n");
}

AliCDBManager *SetOCDB(const Int_t kgrid, const Int_t kraw, const Int_t year, const Int_t xxrun, const Bool_t k1kg)
{
  if(kgrid<0)//no OCDB
    return 0x0;

  TString cpath;
  if(kgrid==0){
    cpath=Form("local:///lustre/alice/alien/alice/data/%d/OCDB/",year);
  }
  else if(kgrid==1){
    cpath="raw://";
  }
  else if(kgrid==2){
    cpath=Form("alien://folder=/alice/data/%d/OCDB",year);
  }
  else{
    printf("kgrid error! %d\n", kgrid);exit(1);
  }

  printf("======> kgrid: %d OCDB: %s\n\n", kgrid, cpath.Data());

  AliCDBManager* cdb = AliCDBManager::Instance();
  cdb->SetDefaultStorage(cpath);
  cdb->SetRun(xxrun);
  cdb->Print();

  if(k1kg){
    printf("\n********* Locking field at 1 kg!! ***********\n\n");
    //official at alien: /alice/cern.ch/user/a/alidaq/LHC11c/TRD2/rec.C
    AliMagF* fld = new AliMagF("map","map",-0.5,-1,AliMagF::k2kG,AliMagF::kNoBeamField,0);
    fld->SetBit(AliMagF::kOverrideGRP);
    TGeoGlobalMagField::Instance()->SetField( fld );
    TGeoGlobalMagField::Instance()->Lock();
  }

  if(kraw){
    printf("======> SetOCDB done! 0\n");
    return cdb;
  }

  AliGeomManager::LoadGeometry();

  if (!TGeoGlobalMagField::Instance()->GetField()) {
    printf("Loading field map...\n");
    AliGRPManager *grpMan = new AliGRPManager();
    grpMan->ReadGRPEntry();
    grpMan->SetMagField();
    delete grpMan;
  }

  printf("======> SetOCDB done! 1\n");
  return cdb;
}

void SetEnv(const TString fin, Bool_t & kraw, Int_t & year, TString & tmpchunk, Int_t & xxrun, Bool_t & k1kg)
{
  kraw = fin.Contains("raw");

  if(fin.Contains("/10000")){
    year = 2010;
  }
  else if(fin.Contains("/11000")){
    year = 2011;
  }
  else if(fin.Contains("/12000")){
    year = 2012;
  }
  else{
    printf("SetEnv error wrong buff for year!!%s\n", fin.Data()); exit(1);
  }

  TString f1= kraw ? fin : fin(0,fin.Last('/'));
  tmpchunk = f1(f1.Last('/')+1,1000);
  
  const TString runstr=tmpchunk(5,6);
  xxrun = runstr.Atoi();

  const TString type = AliTRDdEdxBaseUtils::GetRunType(xxrun);
  if(type.Contains("1KG"))
    k1kg = kTRUE;
  else 
    k1kg = kFALSE;
}

TChain * IniRun(TString fin, TString *chunkss=0x0, const Int_t kgrid = kFALSE, const Bool_t kSetEnv=kTRUE, const Bool_t kFriend = kTRUE)
{
  if(fin.Contains("alien:/")){
    TGrid::Connect("alien://");
  }
  
  if(kSetEnv){
    Bool_t kraw = kFALSE;  
    Int_t year = -999; 
    TString tmpchunk;
    Int_t xxrun = -999;
    Bool_t k1kg = kFALSE;
  
    //----------------------------------------------------------
    //                           Initialize Variables
    //----------------------------------------------------------
    SetEnv(fin, kraw, year, tmpchunk, xxrun, k1kg);
    printf("======> kRaw: %d Year: %d Chunk: %s Run: %d k1kg: %d\n", kraw, year, tmpchunk.Data(), xxrun, k1kg);

    if(chunkss){
      (*chunkss)=tmpchunk;
    } 

    //----------------------------------------------------------
    //                           Setup OCDB
    //----------------------------------------------------------
    
    SetOCDB(kgrid, kraw, year, xxrun, k1kg);
    
    if(kraw){
      printf("======> IniRun done! 0\n\n");
      return 0x0;
    }
  }
  
  //----------------------------------------------------------
  //                           Setup Chain
  //----------------------------------------------------------
  TChain* ch = 0x0;
  if(fin.Contains("AOD")){
    ch = new TChain("aodTree");
    ch->Add(fin);
  }
  else{
    if(!fin.Contains("AliESDs")){
      fin.Append("#AliESDs.root");
    }
    
    ch= new TChain("esdTree");  
    ch->Add(fin);
    
    if(kFriend){
      TChain* chFriend = new TChain("esdFriendTree");
      fin.ReplaceAll("AliESDs.root", "AliESDfriends.root");
      chFriend->Add(fin);
      ch->AddFriend(chFriend);
    }
  }

  printf("======> Chain %s n: %d\n", ch->GetName(), ch->GetListOfFiles()->GetEntries());

  //----------------------------------------------------------
  //----------------------------------------------------------

  printf("======> IniRun done! 1\n\n");
  return ch;
}

#endif
